package com.speedchina.framework.base;

import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.speedchina.framework.exception.BaseSqlException;
import com.speedchina.framework.inter.IdGenerator;
import com.speedchina.framework.inter.StandardFieldValueObtain;
import com.speedchina.framework.utils.ApplicationContextHolder;
import com.speedchina.framework.utils.ReflectionUtils;
import com.speedchina.framework.utils.SnowFlake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 基础Service服务层实现
 *
 * @author hank
 * @create 2018-10-19 上午10:55
 **/
public class TService<D extends IDao<T>,T extends TEntity<T>> extends ServiceImpl<D,T> implements IService<T>{

    @Value("${custom.id-generator:com.speedchina.permission.config.IdGeneratorSnowflake}")
    private  String idGeneratorClassName;

    @Transactional(rollbackFor = {BaseSqlException.class})
    public boolean batchUpdate(T[] ts) {
        return this.saveOrUpdateBatch(Arrays.asList(ts), 30);
    }

    @Transactional(rollbackFor = {BaseSqlException.class})
    public boolean saveOrUpdate4AutoGenId(T entity) {
        StandardFieldValueObtain standardFieldValueObtain = ApplicationContextHolder.getBean(StandardFieldValueObtain.class);
        Class<?> cls = entity.getClass();
        TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
        if (null != tableInfo && StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
            Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
            if (StringUtils.checkValNull(idVal)) {
                // 此处默认使用雪花，当然后续可以使用 雪花算法、分布式ID生成类等
                Serializable serializable = getNextId(entity);
                ReflectionUtils.setFieldValue(entity, tableInfo.getKeyProperty(), serializable);
                //生成创建人和创建时间
                entity.setCreateBy((standardFieldValueObtain != null && standardFieldValueObtain.getOperator() != null) ? standardFieldValueObtain.getOperator() : null);
                entity.setCreateTime((standardFieldValueObtain != null && standardFieldValueObtain.getCurrentTime() != null) ? standardFieldValueObtain.getCurrentTime() : new Date());
                return super.save(entity);
            }
        }
        entity.setUpdateBy((standardFieldValueObtain != null && standardFieldValueObtain.getOperator() != null) ? standardFieldValueObtain.getOperator() : null);
        entity.setUpdateTime((standardFieldValueObtain != null && standardFieldValueObtain.getCurrentTime() != null) ? standardFieldValueObtain.getCurrentTime() : new Date());
        return super.updateById(entity);
    }

    /**
     * @Author xz
     * @Description id获取方法
     * @Date 16:44 2021/4/12
     * @Param [entity]
     * @return java.io.Serializable
     */
    private Serializable getNextId(Object entity) {
        IdGenerator idGenerator = null;
        try {
            //反射获取实例对象
            if(StringUtils.isNotBlank(idGeneratorClassName)){
                Class<?> aClass = Class.forName(idGeneratorClassName);
                idGenerator = (IdGenerator)aClass.newInstance();
            }
        } catch (Exception e) {
            idGenerator = null;
            e.printStackTrace();
        }
        return null == idGenerator ? String.valueOf(SnowFlake.generateId()) : idGenerator.nextId(entity);
    }

    public <M extends T> List<M> queryList(M params) {
        return baseMapper.queryList(null, params);
    }

    public <M extends T> Page queryPage(QueryModel<M> model) {
        if(model == null){
            model = new QueryModel<M>();
        }
        Page page = new Page(model.getPage(), model.getLimit());
        page.setRecords(baseMapper.queryList(page, model.getM()));
        return page;
    }

    public <M extends T> M get(M params) {
        return baseMapper.get(params);
    }

    public boolean deleteBatch(List<Serializable> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

}
